﻿using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
using System.Configuration;
using System.Reflection;
using Zhp.Common.Helper;

namespace Zhp.Common.Appsetting
{
    public static class AppSettingHelper
    {
        /// <summary>
        /// 此方法只能在AddAppSettingOptions()调用之后使用
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static T GetOptions<T>() where T : class
        {
            var options = AppHelper.ServiceCollection.BuildServiceProvider().GetService<IOptionsMonitor<T>>();
            if (options == null)
            {
                throw new ArgumentNullException($"{typeof(T).Name}类型未注册");
            }
            return options.CurrentValue;
        }

        /// <summary>
        /// 此方法只能在AddAppSettingOptions()调用之后使用
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        /// <exception cref="ArgumentNullException"></exception>
        public static T GetOptions<T>(this IServiceCollection services) where T : class
        {
            var options = services.BuildServiceProvider().GetService<IOptionsMonitor<T>>();
            if (options == null)
            {
                throw new ArgumentNullException($"{typeof(T).Name}类型未注册");
            }
            return options.CurrentValue;
        }

        /// <summary>
        /// 将配置文件和对象绑定
        /// </summary>
        /// <param name="services"></param>
        /// <returns></returns>
        public static IServiceCollection AddAppSettingOptions(this IServiceCollection services)
        {
            var optionTypes = Assembly.GetExecutingAssembly().GetTypes();
            foreach (var type in optionTypes)
            {
                var attr = type.GetCustomAttribute<AppSettingAttribute>();
                if (attr != null)
                {
                    var configurationSection = AppHelper.Configuration.GetSection(attr.Section);
                    if (configurationSection != null)
                    {
                        //将配置注册到服务中
                        //services.Configure<item>(configurationSection);
                        //反射调用以上方法将options注入的服务中
                        var configureMethod = typeof(OptionsConfigurationServiceCollectionExtensions)
                                            .GetMethods(BindingFlags.Public | BindingFlags.Static)
                                            .FirstOrDefault(m => m.Name == "Configure" && m.IsGenericMethod && m.GetParameters().Length == 2
                                            && m.GetParameters()[0].ParameterType == typeof(IServiceCollection)
                                            && m.GetParameters()[1].ParameterType == typeof(IConfiguration));

                        if (configureMethod != null)
                        {
                            var genericConfigureMethod = configureMethod.MakeGenericMethod(type);
                            genericConfigureMethod.Invoke(null, new object[] { services, configurationSection });
                        }
                    }
                }
            }
            return services;
        }
    }
}
